<?php

namespace SunAdmin\Service\Ws;

use think\Exception;
use think\facade\Cache;

/**
 * WebSocket服务基类
 * 统一处理连接类型校验和缓存驱动验证
 */
abstract class BaseWebSocketService
{
    protected string $connectionType; // 连接类型：admin 或 client
    protected string $cachePrefix;    // 缓存前缀
    
    // 允许的连接类型 - 集中管理，方便扩展
    protected const ALLOWED_CONNECTION_TYPES = [
        'admin',  // 后台管理系统
        'client', // 客户端用户
        // 'api',     // API服务（预留）
        // 'mobile',  // 移动端（预留）
    ];
    
    // 要求的缓存驱动类型
    protected const REQUIRED_CACHE_DRIVER = 'redis';

    public function __construct(string $connectionType)
    {
        // 严格校验连接类型
        $this->validateConnectionType($connectionType);
        
        // 验证缓存驱动
        $this->validateCacheDriver();
        
        $this->connectionType = $connectionType;
        $this->cachePrefix = $connectionType . '_ws';
    }
    
    /**
     * 获取连接类型
     */
    public function getConnectionType(): string
    {
        return $this->connectionType;
    }
    
    /**
     * 获取缓存前缀
     */
    public function getCachePrefix(): string
    {
        return $this->cachePrefix;
    }
    
    /**
     * 获取所有允许的连接类型
     */
    public static function getAllowedConnectionTypes(): array
    {
        return self::ALLOWED_CONNECTION_TYPES;
    }
    
    /**
     * 检查连接类型是否有效
     */
    public static function isValidConnectionType(string $connectionType): bool
    {
        return in_array($connectionType, self::ALLOWED_CONNECTION_TYPES);
    }
    
    /**
     * 严格校验连接类型
     */
    private function validateConnectionType(string $connectionType): void
    {
        if (!self::isValidConnectionType($connectionType)) {
            throw new Exception(sprintf(
                "非法的连接类型: %s，只允许: %s", 
                $connectionType, 
                implode(', ', self::ALLOWED_CONNECTION_TYPES)
            ));
        }
    }
    
    /**
     * 验证缓存驱动是否为Redis
     */
    private function validateCacheDriver(): void
    {
        $cacheConfig = config('cache.default');
        $storeConfig = config("cache.stores.{$cacheConfig}");
        
        if (!$storeConfig || strtolower($storeConfig['type']) !== self::REQUIRED_CACHE_DRIVER) {
            throw new Exception(sprintf(
                "WebSocket服务要求缓存驱动必须为%s，当前驱动为: %s", 
                self::REQUIRED_CACHE_DRIVER,
                $storeConfig['type'] ?? 'unknown'
            ));
        }
    }
    
    /**
     * 获取Redis实例
     */
    protected function getRedisInstance()
    {
        $redis = Cache::store()->handler();
        
        if (!$redis instanceof \Redis && !$redis instanceof \Predis\Client) {
            throw new Exception("缓存驱动不是Redis实例");
        }
        
        return $redis;
    }
    
    /**
     * 使用Redis的keys命令获取缓存键
     */
    protected function getRedisKeys(string $pattern): array
    {
        try {
            $redis = $this->getRedisInstance();
            
            // 使用Redis的keys命令
            if ($redis instanceof \Redis) {
                $keys = $redis->keys($pattern);
            } else {
                // Predis客户端
                $keys = $redis->keys($pattern);
            }
            
            return is_array($keys) ? $keys : [];
            
        } catch (\Throwable $e) {
            throw new Exception("获取Redis keys失败: " . $e->getMessage());
        }
    }
}